package com.movitech.mobile.ddzy.zuulfilter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.context.annotation.Configuration;

import com.google.gson.Gson;
import com.movitech.mobile.cz.base.common.util.CommonConstants;
import com.movitech.mobile.cz.base.common.util.HeadersUtils;
import com.movitech.mobile.cz.base.common.util.StringUtils;
import com.movitech.mobile.cz.base.common.utils.CheckResult;
import com.movitech.mobile.cz.base.common.utils.JwtUtils;
import com.movitech.mobile.cz.base.modules.controller.RestReturnResult;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;

/***
 * 用户数据验证
 * @author Wayne.Zhang
 *
 */
@Configuration
public class UserFilter extends ZuulFilter {

	@Value("${zuul.jwt.token.ttl}")
	private Long jwtTokenTTL;
	
	@Value("${zuul.jwt.refresh.token.ttl}")
	private Long jwtRefreshTokenTTL;
	
	/**
	 * 执行业务操作
	 */
	@SuppressWarnings("unused")
	@Override
	public Object run() {
		RequestContext ctx = RequestContext.getCurrentContext();
		HttpServletRequest request = ctx.getRequest();
		HttpServletResponse response = ctx.getResponse();
		System.out.println(String.format("UserFilter---> %s >>> %s", request.getMethod(), request.getRequestURL().toString()));

		boolean isOK = false;
		String errorMsg = "";
		
		if(StringUtils.equalsIgnoreCase(request.getMethod(), "OPTIONS")){
            ctx.addZuulResponseHeader("Access-Control-Allow-Origin", "*");
            ctx.addZuulResponseHeader("Access-Control-Allow-Methods", "*");
//            ctx.addZuulResponseHeader("Access-Control-Allow-Headers", "*");
			ctx.addZuulResponseHeader("Access-Control-Allow-Headers", "token,refresh_token,regenerate_token_flag,Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With");
			ctx.addZuulResponseHeader("Access-Control-Max-Age", "1800000");
            ctx.addZuulResponseHeader("Content-Length", "0");
            ctx.addZuulResponseHeader("Content-Type", "text/plain");
            
            ctx.setSendZuulResponse(false);//会进行路由，也就是会调用api服务提供者  
            ctx.setResponseStatusCode(200); 
        }else{
			ctx.addZuulResponseHeader("Access-Control-Expose-Headers", "token");
			ctx.addZuulResponseHeader("Access-Control-Expose-Headers", "refresh_token");
			ctx.addZuulResponseHeader("Access-Control-Expose-Headers", "regenerate_token_flag");
        	ctx.addZuulResponseHeader("Access-Control-Allow-Origin", "*");
            ctx.addZuulResponseHeader("Access-Control-Allow-Methods", "*");
            ctx.addZuulResponseHeader("Access-Control-Allow-Headers", "*");
            ctx.addZuulResponseHeader("Access-Control-Max-Age", "1800000");
            

    		Gson gson = new Gson();
            String requestURL = request.getRequestURL().toString();
            if(!StringUtils.containsIgnoreCase(requestURL, "/public/")) {//去除公共的接口方法
    			String token = HeadersUtils.getHeadByKey(request, "token");
    			String refreshToken = HeadersUtils.getHeadByKey(request, "refresh_token");
            	if(StringUtils.isEmpty(token)) {
            		errorMsg = gson.toJson(new RestReturnResult<Object>(CommonConstants.FAIL,"token不能为空"));
					ctx.addZuulResponseHeader("regenerate_token_flag", "2");
                }else {
                	CheckResult checkResult = JwtUtils.parseJWT(token);
                	if(checkResult.isSuccess()) {
                		ctx.addZuulRequestHeader("user_info", checkResult.getSubject());
                		isOK = true;
                	}else {
                		if(StringUtils.equalsIgnoreCase(checkResult.getErrorCode(), JwtUtils.JWT_ERRCODE_EXPIRED)) {
                			if(StringUtils.isEmpty(refreshToken)) {
                				errorMsg = gson.toJson(new RestReturnResult<Object>(CommonConstants.FAIL,"token验证失败"));
								ctx.addZuulResponseHeader("regenerate_token_flag", "2");
                	        }else {
                	        	CheckResult checkResultRefresh = JwtUtils.parseJWT(refreshToken);
                	        	if(checkResultRefresh.isSuccess()) {
                	        		ctx.addZuulRequestHeader("user_info", checkResultRefresh.getSubject());
                	        		
                	        		ctx.addZuulResponseHeader("token", JwtUtils.createJWT(checkResultRefresh.getSubject(), jwtTokenTTL));
                	        		ctx.addZuulResponseHeader("refresh_token", JwtUtils.createJWT(checkResultRefresh.getSubject(), jwtRefreshTokenTTL));
            						ctx.addZuulResponseHeader("regenerate_token_flag", "1");
                            		isOK = true;
                	        	}else {
                	        		errorMsg = gson.toJson(new RestReturnResult<Object>(CommonConstants.FAIL,"token验证失败"));
									ctx.addZuulResponseHeader("regenerate_token_flag", "2");
                	        	}
                	        }
                		}else {
                			errorMsg = gson.toJson(new RestReturnResult<Object>(CommonConstants.FAIL,"token不能为空"));
							ctx.addZuulResponseHeader("regenerate_token_flag", "2");
                		}
                	}
                }
            }else {
            	isOK = true;
            }
            
            if(isOK){
                ctx.setSendZuulResponse(true);//会进行路由，也就是会调用api服务提供者  
                ctx.setResponseStatusCode(200); 
            }else{  
                ctx.setSendZuulResponse(false);//不需要进行路由，也就是不会调用api服务提供者  
                ctx.setResponseStatusCode(401);  
                ctx.setResponseBody(errorMsg);// 返回错误内容    //返回内容给客户端  
            }  
        }
        
		return null;
	}

	/**
	 * 是否应该执行该过滤器，如果是false，则不执行该filter
	 */
	@Override
	public boolean shouldFilter() {
		return true;
	}

	/**
	 * 同filterType类型中，order值越大，优先级越低
	 */
	@Override
	public int filterOrder() {
		return 1;
	}

	/**
	 * 过滤器类型 顺序: pre ->routing -> post ,以上3个顺序出现异常时都可以触发error类型的filter
	 */
	@Override
	public String filterType() {
		return FilterConstants.PRE_TYPE;
	}

}
